package Service.Impl;

import Service.IMyChangeService;

import javax.swing.*;
import java.nio.charset.StandardCharsets;
import java.text.DecimalFormat;
import java.util.Collections;

public class MyChangeServiceImpl implements IMyChangeService {
    private static String hexStr =  "0123456789ABCDEF";

    @Override
    public String intToBinary(int n){
        String str = "";

        while(n != 0) {
            str = n%2 + str;
            n = n/2;
        }
        int numZero = 4 - str.length()%4;
        for (int i=0 ; i<numZero ; i++) {
            str = '0' + str;
        }
        return str;
    }

    // 先用正数转化为二进制
    public String changeBackTwo(byte[] bytes) {
        String str2 = "";
        for (int i=0 ; i<bytes.length; i++) {
            if (bytes[i] == 1) {
                str2 += '0';
            } else if (bytes[i] == 0) {
                str2 += '1';
            }
        }
        String add_1 = Solution(str2, "1");
        return add_1;
    }

    public String changeTwo(byte[] bytes) {
        String str2 = "";
        byte temp;
        for (int i = 0; i < bytes.length; i++) {
            temp = bytes[i];
            bytes[i] = (byte) (~temp);
            str2 += Integer.toBinaryString((bytes[i] & 0xFF) + 0x100).substring(1);
        }
        // 取反后+1
        String add_1 = Solution(str2, "1");
        return add_1;
    }

    public static String Solution(String a, String b) {
        StringBuilder ans = new StringBuilder();
        int ca = 0;
        for (int i = a.length() - 1, j = b.length() - 1; i >= 0 || j >= 0; i--, j--) {
            int sum = ca;
            sum += i >= 0 ? a.charAt(i) - '0' : 0;
            sum += j >= 0 ? b.charAt(j) - '0' : 0;
            ans.append(sum % 2);
            ca = sum / 2;
        }
        ans.append(ca == 1 ? ca : "");
        return ans.reverse().toString();
    }

    public byte[] changeToByte(String decimal) {
        char[] chars = new char[decimal.length()];
        byte[] bytes = new byte[decimal.length()];
        byte[] resultBytes = new byte[32];
        for (int i=0 ; i<decimal.length() ; i++) {
            chars[i] = decimal.charAt(i);
            if (chars[i] == '1') {
                bytes[i] = 1;
            } else if (chars[i] == '0') {
                bytes[i] = 0;
            }
        }
        if (bytes.length <= 32) {
            //String tempZero = String.join(,Collections.nCopies(32-bytes.length, "0"));
            for (int i=0 ; i<(32-bytes.length) ; i++) {
                resultBytes[i] = 0;
            }
            int len = 0;
            for (int j=32-bytes.length ; j<32 ; j++) {
                resultBytes[j] = bytes[len];
                len++;
            }
        }
        return resultBytes;
    }

    public String parseByte2HexStr(byte buf[]) {
        String result = "";
        int tempSum;
        int times = buf.length/4;
        for (int i=0,j=0 ; i<buf.length&j<times ; i+=4,j++) {
            tempSum = 0;
            if (buf[i] == 1) {tempSum += 8;}
            if (buf[i+1] == 1) {tempSum += 4;}
            if (buf[i+2] == 1) {tempSum += 2;}
            if (buf[i+3] == 1) {tempSum += 1;}
            result += hexStr.charAt(tempSum);
        }
//        tempSum = 0;
//        int lessLength = buf.length - 4*times, location = 4*times;
//        if (lessLength == 3) {
//            if (buf[location] == 1) {tempSum += 4;}
//            if (buf[location+1] == 1) {tempSum += 2;}
//            if (buf[location+2] == 1) {tempSum += 1;}
//            result += hexStr.charAt(tempSum);
//        } else if (lessLength == 2) {
//            if (buf[location] == 1) {tempSum += 2;}
//            if (buf[location+1] == 1) {tempSum += 1;}
//            result += hexStr.charAt(tempSum);
//        } else if (lessLength == 1) {
//            if (buf[location] == 1) {tempSum += 1;}
//            result += hexStr.charAt(tempSum);
//        }
        return result;
    }

    // 浮点数二进制转换
    public String FloatToBinary(float n) {
        int signBit;//符号位
        // DecimalFormat #阿拉伯数字如果不存在就显示为空
        String s = (new DecimalFormat("################.######")).format(n);
        if (n == 0) {
            signBit = 0;
        } else if (n < 0) {
            signBit = 1;
            // 把负号去掉
            s = s.substring(1);
        } else {
            signBit = 0;
        }

        String intFloat[] = s.split("\\.");
        // 整数部分 intPart 小数部分 floatPart 分割数据 划分整数和小数部分
        int intPart = Integer.valueOf(intFloat[0]);
        float floatPart = Float.valueOf("0." + intFloat[1]);

        // 整数部分二进制 由于最初不清楚整数到底是几位数，设置标志isReady遍历，
        // 当intPart/2的i次方大于等于1时isReady有值，然后从第i为开始转化2进制（可能存在长度为0的情况）
        boolean isReady = false;
        String str_intpart = "";
        for (int i = 31; i >= 0; i--) {
            if (((intPart >> i) & 1) == 1) {
                isReady = true;
            }
            if (isReady) {
                str_intpart += ((intPart >> i) & 1) == 1 ? 1 : 0;
            }
        }

        // 乘2取整法处理小数部分，只要小数部分处理后不等于0，就先将小数部分乘2
        // 之后对应两种情况：1、大于1，将其减1，小数部分对应位置为1
        //               2、小于1，小数部分对应位置为0（重要算法）
        String str_floartPart = "";
        while (floatPart != 0) {
            floatPart *= 2;
            if (floatPart >= 1) {
                floatPart -= 1;
                str_floartPart += 1;
            } else str_floartPart += 0;
        }

        // 将已得到的整数部分和小数部分连接，末尾不够用0补齐，
        String str_int_float = str_intpart + str_floartPart + "0000000000000000000000000000000";
        //现在得到二进制下的："整数(.)小数"格式。考虑规格化
        int diff = 0;//  规格化所要将小数部分移动的位数，主要是针对整数部分为0的
        int intlen = str_intpart.length();
        str_intpart = str_int_float.substring(0, 1);
        str_floartPart = str_int_float.substring(1, 23);
        // 整数部分为0将小数点右移，整数部分长度为1；若大于0则长度为其本身长度
        while (str_intpart.charAt(0) != '1') {
            str_intpart = str_floartPart.substring(0, 1);
            str_floartPart = str_floartPart.substring(1);
            diff++;
        }

        // 规格化所带来的指数的移动 整数部分存在 即长度不为0 那么直接返回长度-1
        // 长度为0时， 前面小数点右移了几位就取反-1
        int expChange = intlen != 0 ? intlen - 1 : -diff - 1;

        //得到8位指数部分；
        int exponential = expChange + 127;//真正的指数
        String exp = "";  //指数
        // 二进制转化
        for (int i = 7; i >= 0; i--) {
            exp += ((exponential >> i) & 1) == 1 ? 1 : 0;
        }

        //得到23位底数部分
        String base = str_floartPart;
        int len = base.length();
        for (int i = 0; i < 23 - len; i++) {
            base += 0;
        }
        String endTwo = signBit + exp + base;
        return endTwo.substring(0, 32);
    }
}
